#include "boot_logo.h"

#if (defined _BOARD_DB_M3511_01V01_ || \
     defined _BOARD_DB_M3822_01V01_)

struct vdec_device*  g_decv_dev = NULL;
struct vpo_device*   g_vpo_dev = NULL;
struct vpo_device*   g_sd_vpo_dev = NULL;

UINT32 g_otp_set_vdac_fs=0;
static INT32 videologo_playback_end = 0;
static INT32 flag_changed = 0;

enum TVSystem logo_tvsys_hd_to_sd(enum TVSystem tvsys)
{
	if (tvsys == PAL_M || tvsys == PAL_N)
		return tvsys;
	else if (tvsys == NTSC || tvsys == LINE_720_30 || tvsys == LINE_1080_30 || tvsys == LINE_1080_60)
		return NTSC;
	else
		return PAL;
}

enum TVSystem tvmode_to_tvsys(UINT8 tv_mode, UINT8 scart_out)
{
    enum TVSystem eTVSys = TV_MODE_PAL;
    
    switch(tv_mode)
	{
        case TV_MODE_PAL:			
            eTVSys = PAL;
            break;
    	case TV_MODE_PAL_N:	
            eTVSys = PAL_N;
            break;
    	case TV_MODE_NTSC358:
            eTVSys = NTSC;
            break;
    	case TV_MODE_PAL_M:
            eTVSys = PAL_M;
            break;
    	case TV_MODE_NTSC443:
            eTVSys = NTSC_443;
            break;
    	case TV_MODE_SECAM:
            eTVSys = SECAM;
            break;		
    	case TV_MODE_480P:			
            eTVSys = NTSC;
            break;
    	case TV_MODE_576P:			
            eTVSys = PAL;
            break;
    	case TV_MODE_720P_50:	
            eTVSys = LINE_720_25;
            break;
    	case TV_MODE_720P_60:		
            eTVSys = LINE_720_30;
            break;
    	case TV_MODE_1080I_25:		
            eTVSys = LINE_1080_25;
            break;
    	case TV_MODE_1080I_30:		
            eTVSys = LINE_1080_30;
            break;
    	case TV_MODE_1080P_25:
            eTVSys = LINE_1080_25;
            break;
    	case TV_MODE_1080P_30:
            eTVSys = LINE_1080_30;
            break;
    	case TV_MODE_1080P_24:		
            eTVSys = LINE_1080_24;
            break;
    	case TV_MODE_1080P_50:		
            eTVSys = LINE_1080_50;
            break;
    	case TV_MODE_1080P_60:
            eTVSys = LINE_1080_60;
            break;
        default:
    		eTVSys = LINE_1080_25;
            break;	
	} 

    if(tv_mode == TV_MODE_AUTO && scart_out == SCART_RGB && eTVSys >= LINE_720_25)
    {
        eTVSys = logo_tvsys_hd_to_sd(eTVSys);
    }
    
    return eTVSys;
}

void bl_get_show_para(enum TVSystem eTVSys, UINT16 *width, UINT16 *height)
{
    UINT16 screen_width = 1920;
    UINT16 screen_height = 1080;
    switch(eTVSys)
	{
        case PAL:
		case PAL_N:	
		case PAL_NC:	
		case PAL_60:
			screen_width = 720;
			screen_height = 576;
			break;
		case PAL_M:
		case NTSC:
		case NTSC_443:
			screen_width = 720;
			screen_height = 480;
			break;
		case LINE_720_25:
		case LINE_720_30:
			screen_width = 1280;
			screen_height = 720;
			break;
        case LINE_1080_25:
        case LINE_1080_30:
        case LINE_1080_24:
        case LINE_1080_50:
        case LINE_1080_60:
            screen_width = 1920;
            screen_height = 1080;            
            break;
        default:
            break;     
    }

    *width = screen_width;
    *height = screen_height;
    
}

static enum DisplayMode sys_data_get_display_mode(UINT8 tv_ratio, UINT8 display_mode)
{
    enum DisplayMode e169DisplayMode;

    if(tv_ratio == TV_ASPECT_RATIO_AUTO)
        e169DisplayMode = NORMAL_SCALE;    
    else if(display_mode == DISPLAY_MODE_LETTERBOX)
        e169DisplayMode = LETTERBOX;
    else if(display_mode == DISPLAY_MODE_PANSCAN)
        e169DisplayMode = PANSCAN;
    else 
        e169DisplayMode = NORMAL_SCALE;
    
    //if(eTVAspect == TV_16_9)
    if(tv_ratio == TV_ASPECT_RATIO_169)
        e169DisplayMode = PILLBOX;

    return e169DisplayMode;
}

INT32 bl_get_tv_set(UINT8 *p_tv_mode, UINT8 *p_scart_out, UINT8 *p_tv_ratio, UINT8 *p_display_mode)
{
    // boot read temp data
    INT32 ret = RET_FAILURE;
    UINT32 chunk_id = 0;
    UINT32 db_len = 0;
    UINT32 db_addr = 0;
    UINT8 sys_data[AV_SET_OFFSET + AV_SET_LEN]={0};
    UINT8 tv_mode = 0;      // : 5 // enum TV_SYS_TYPE
	UINT8 tv_ratio = 0; 	// : 3
    UINT8 display_mode = 0; // : 4
	UINT8 scart_out = 0; 	// : 4

    if(NULL == p_tv_mode || NULL == p_scart_out || NULL == p_tv_ratio || NULL == p_display_mode)
    {
       FIXED_PRINTF("%s invalid input!!!\n",__FUNCTION__);
       return RET_FAILURE;
    }
    
    memset(sys_data,0,sizeof(sys_data));
    
    chunk_id = 0x04FB0100; // userdb
    bl_get_chunk_len(chunk_id, &db_addr, &db_len);
    db_len = db_len - (64*1024);
    init_tmp_info(db_addr + db_len, 64*1024);
    FIXED_PRINTF("%s db_addr=0x%x db_len=0x%x AV_SET_LEN=%d\n",__FUNCTION__,db_addr,db_len,AV_SET_LEN);
    ret = load_tmp_data((UINT8*)sys_data,sizeof(sys_data));

    if(ret == SUCCESS)
    {
        FIXED_PRINTF("%s load_tmp_data RET_SUCCESS!\n",__FUNCTION__);
        FIXED_PRINTF("sys_data[%d]=%d\n",AV_SET_OFFSET,sys_data[AV_SET_OFFSET]);
        FIXED_PRINTF("sys_data[%d]=%d\n",AV_SET_OFFSET+1,sys_data[AV_SET_OFFSET+1]);
        tv_mode = sys_data[AV_SET_OFFSET] & 0x1F;
        tv_ratio = (sys_data[AV_SET_OFFSET] >> 5) & 0x07;

        display_mode = sys_data[AV_SET_OFFSET+1] & 0x0F;
        scart_out = (sys_data[AV_SET_OFFSET+1] >> 4) & 0x0F;

        FIXED_PRINTF("tv_mode=%d\n",tv_mode);
        FIXED_PRINTF("tv_ratio=%d\n",tv_ratio);
        FIXED_PRINTF("display_mode=%d\n",display_mode);
        FIXED_PRINTF("scart_out=%d\n",scart_out);

        *p_tv_mode = tv_mode;
        *p_scart_out = scart_out;
        *p_tv_ratio = tv_ratio;
        *p_display_mode = display_mode;
    }
    else
        FIXED_PRINTF("%s load_tmp_data Fail!\n",__FUNCTION__);
    
    return ret;
}

BOOL logo_data_is_progressive(enum TV_SYS_TYPE eTVMode)
{
	BOOL bProgressive =FALSE;
	
//#ifdef HDTV_SUPPORT
	switch (eTVMode)
	{
	case TV_MODE_576P:
	case TV_MODE_480P:
	case TV_MODE_720P_50:
	case TV_MODE_720P_60:
	case TV_MODE_1080P_25:
	case TV_MODE_1080P_30:
	case TV_MODE_1080P_24:
	case TV_MODE_1080P_50:
	case TV_MODE_1080P_60:
		bProgressive = TRUE;
		break;
	case TV_MODE_1080I_25:
	case TV_MODE_1080I_30:
		bProgressive = FALSE;
		break;
	}
//#endif
	return bProgressive;
}

void avStart(enum TVSystem  tvsys, BOOL bprogressive)
{
	struct VDecPIPInfo vInitInfo;
	struct MPSource_CallBack vMPCallBack;
	struct PIPSource_CallBack vPIPCallBack;
	struct VDec_PullDown_Opr tPullDownCallBack;
    struct vp_win_config_para win_para;
	
	vdec_profile_level(g_decv_dev, MP_HL, NULL);

    vInitInfo.adv_setting.init_mode = 0;
    vInitInfo.adv_setting.out_sys = tvsys;
    vInitInfo.adv_setting.bprogressive = bprogressive;

    vdec_set_output ( g_decv_dev, MP_MODE, &vInitInfo, &vMPCallBack, &vPIPCallBack );
    vpo_win_mode ( g_vpo_dev, VPO_MAINWIN, &vMPCallBack, &vPIPCallBack );

    vdec_sync_mode ( g_decv_dev, VDEC_SYNC_FREERUN, VDEC_SYNC_I | VDEC_SYNC_P | VDEC_SYNC_B );

}

static void InitVPPara_sd(struct VP_InitInfo *pVPInitInfo,UINT8 tv_mode, UINT8 scart_out, UINT8 tv_ratio, UINT8 display_mode)
{
	int i;
    enum TVSystem eTVSys = 0;

    eTVSys = tvmode_to_tvsys(tv_mode, scart_out);
	MEMSET(pVPInitInfo, 0, sizeof(struct VP_InitInfo));

    pVPInitInfo->device_priority = VPO_AUTO_DUAL_OUTPUT;    // S3602F use VCAP
	//api set backgound color]
	pVPInitInfo->tInitColor.uY = 0x10;
	pVPInitInfo->tInitColor.uCb= 0x80;
	pVPInitInfo->tInitColor.uCr= 0x80;
	//set advanced control
	pVPInitInfo->bBrightnessValue = 0;
	pVPInitInfo->fBrightnessValueSign = TRUE;
	pVPInitInfo->wContrastValue = 0;
	pVPInitInfo->fContrastSign = TRUE;
	pVPInitInfo->wSaturationValue = 0;
	pVPInitInfo->fSaturationValueSign = TRUE;
	pVPInitInfo->wSharpness = 0;
	pVPInitInfo->fSharpnessSign = TRUE;
	pVPInitInfo->wHueSin = 0;
	pVPInitInfo->fHueSinSign = TRUE;
	pVPInitInfo->wHueCos = 0;
	pVPInitInfo->fHueCosSign = TRUE;
	//VPO_Zoom
	pVPInitInfo->tSrcRect.uStartX = 0;
	pVPInitInfo->tSrcRect.uWidth= PICTURE_WIDTH;
	pVPInitInfo->tSrcRect.uStartY= 0;
	pVPInitInfo->tSrcRect.uHeight= PICTURE_HEIGHT;
	pVPInitInfo->DstRect.uStartX = 0;
	pVPInitInfo->DstRect.uWidth= SCREEN_WIDTH;
	pVPInitInfo->DstRect.uStartY= 0;
	pVPInitInfo->DstRect.uHeight= SCREEN_HEIGHT;

	//VPO_SetAspect
	pVPInitInfo->eTVAspect = (tv_ratio ==TV_ASPECT_RATIO_169)? TV_16_9 : TV_4_3;
	pVPInitInfo->eDisplayMode = sys_data_get_display_mode(tv_ratio, display_mode);
	pVPInitInfo->uNonlinearChangePoint = 111;
	pVPInitInfo->uPanScanOffset = 90;
	//VPO_SetOutput
	for(i=0;i<VP_DAC_TYPENUM;i++)
		pVPInitInfo->pDacConfig[i].bEnable = FALSE;

//CVBS_1

   	pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].bEnable = TRUE;

    if (scart_out == SCART_YUV)
    {
        if((tv_mode == TV_MODE_PAL)||(tv_mode == TV_MODE_NTSC358))
        {
            pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].bEnable = FALSE;
        }
    	pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].tDacIndex.uDacFirst = CVBS_DAC;
    }
    else
    {
    	pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].tDacIndex.uDacFirst = 0xFF;
    }

	pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].eVGAMode= VGA_NOT_USE;
	pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].bProgressive= FALSE;

	pVPInitInfo->pDacConfig[YUV_1].bEnable = FALSE;

	//RGB
	pVPInitInfo->pDacConfig[VDAC_USE_RGB_TYPE].bEnable = FALSE;

	pVPInitInfo->eTVSys = logo_tvsys_hd_to_sd(eTVSys);

	pVPInitInfo->bWinOnOff = FALSE;

	pVPInitInfo->uWinMode = VPO_MAINWIN;//|VPO_PIPWIN;
	pVPInitInfo->tPIPCallBack.RequestCallback = NULL;
	pVPInitInfo->tPIPCallBack.ReleaseCallback= NULL;
	pVPInitInfo->pSrcChange_CallBack=NULL;
}


static void InitVPPara(struct VP_InitInfo *pVPInitInfo, UINT8 tv_mode, UINT8 scart_out, UINT8 tv_ratio, UINT8 display_mode)
{
	int i;
    BOOL vdac_progressive = FALSE;
    enum TVSystem eTVSys = 0;

    eTVSys = tvmode_to_tvsys(tv_mode, scart_out);
	//api set backgound color]
	pVPInitInfo->tInitColor.uY = 0x10;
	pVPInitInfo->tInitColor.uCb= 0x80;
	pVPInitInfo->tInitColor.uCr= 0x80;

	//set advanced control
	pVPInitInfo->bBrightnessValue = 0;
	pVPInitInfo->fBrightnessValueSign = TRUE;
	pVPInitInfo->wContrastValue = 0;
	pVPInitInfo->fContrastSign = TRUE;
	pVPInitInfo->wSaturationValue = 0;
	pVPInitInfo->fSaturationValueSign = TRUE;
	pVPInitInfo->wSharpness = 0;
	pVPInitInfo->fSharpnessSign = TRUE;
	pVPInitInfo->wHueSin = 0;
	pVPInitInfo->fHueSinSign = TRUE;
	pVPInitInfo->wHueCos = 0;
	pVPInitInfo->fHueCosSign = TRUE;
	pVPInitInfo->bCCIR656Enable = FALSE;
	//VPO_Zoom
	pVPInitInfo->tSrcRect.uStartX = 0;
	pVPInitInfo->tSrcRect.uWidth= PICTURE_WIDTH;
	pVPInitInfo->tSrcRect.uStartY= 0;
	pVPInitInfo->tSrcRect.uHeight= PICTURE_HEIGHT;
	pVPInitInfo->DstRect.uStartX = 0;
	pVPInitInfo->DstRect.uWidth= SCREEN_WIDTH;
	pVPInitInfo->DstRect.uStartY= 0;
	pVPInitInfo->DstRect.uHeight= SCREEN_HEIGHT;

	//VPO_SetAspect
	pVPInitInfo->eTVAspect = (tv_ratio ==TV_ASPECT_RATIO_169)? TV_16_9 : TV_4_3;
	pVPInitInfo->eDisplayMode = sys_data_get_display_mode(tv_ratio, display_mode);
	pVPInitInfo->uNonlinearChangePoint = 111;
	pVPInitInfo->uPanScanOffset = 90;
	//VPO_SetOutput
	for(i=0;i<VP_DAC_TYPENUM;i++)
		pVPInitInfo->pDacConfig[i].bEnable = FALSE;

	pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].bEnable = FALSE;
	pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].tDacIndex.uDacFirst = CVBS_DAC;
	pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].eVGAMode= VGA_NOT_USE;
	pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].bProgressive= FALSE;

	pVPInitInfo->pDacConfig[YUV_1].bEnable = FALSE;
	pVPInitInfo->pDacConfig[YUV_1].tDacIndex.uDacFirst = YUV_DAC_Y;
	pVPInitInfo->pDacConfig[YUV_1].tDacIndex.uDacSecond= YUV_DAC_U;
	pVPInitInfo->pDacConfig[YUV_1].tDacIndex.uDacThird= YUV_DAC_V;
	pVPInitInfo->pDacConfig[YUV_1].eVGAMode= VGA_NOT_USE;
	pVPInitInfo->pDacConfig[YUV_1].bProgressive= FALSE;

	pVPInitInfo->pDacConfig[VDAC_USE_RGB_TYPE].bEnable = TRUE;
	pVPInitInfo->pDacConfig[VDAC_USE_RGB_TYPE].tDacIndex.uDacFirst = RGB_DAC_R;
	pVPInitInfo->pDacConfig[VDAC_USE_RGB_TYPE].tDacIndex.uDacSecond= RGB_DAC_G;
	pVPInitInfo->pDacConfig[VDAC_USE_RGB_TYPE].tDacIndex.uDacThird= RGB_DAC_B;
	pVPInitInfo->pDacConfig[VDAC_USE_RGB_TYPE].eVGAMode= VGA_NOT_USE;
	pVPInitInfo->pDacConfig[VDAC_USE_RGB_TYPE].bProgressive= FALSE;

    if (scart_out == SCART_YUV)
    {
    	pVPInitInfo->eTVSys = eTVSys;

        vdac_progressive = logo_data_is_progressive(tv_mode);

        if((tv_mode == TV_MODE_PAL)||(tv_mode == TV_MODE_NTSC358))
        {
            pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].bEnable = TRUE;
        }
        else
            pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].bEnable = FALSE;
    	pVPInitInfo->pDacConfig[VDAC_USE_YUV_TYPE].bEnable = TRUE;
        pVPInitInfo->pDacConfig[VDAC_USE_YUV_TYPE].bProgressive = vdac_progressive;
    	pVPInitInfo->pDacConfig[VDAC_USE_RGB_TYPE].bEnable = FALSE;
    }
    else
    { 
        pVPInitInfo->eTVSys = eTVSys;

	    pVPInitInfo->pDacConfig[VDAC_USE_CVBS_TYPE].bEnable = TRUE;
	    pVPInitInfo->pDacConfig[VDAC_USE_RGB_TYPE].bEnable = TRUE;
        pVPInitInfo->pDacConfig[VDAC_USE_YUV_TYPE].bEnable = FALSE;
        pVPInitInfo->pDacConfig[VDAC_USE_YUV_TYPE].bProgressive = FALSE;
    }

	pVPInitInfo->bWinOnOff = FALSE;
	pVPInitInfo->uWinMode = VPO_MAINWIN;//|VPO_PIPWIN;
	pVPInitInfo->tPIPCallBack.RequestCallback = NULL;
	pVPInitInfo->tPIPCallBack.ReleaseCallback= NULL;
	pVPInitInfo->pSrcChange_CallBack=NULL;
}

RET_CODE avInit(UINT8 tv_mode, UINT8 scart_out, UINT8 tv_ratio, UINT8 display_mode)
{
	struct VP_InitInfo	tVPInitInfo;

	g_vpo_dev = (struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 0);
    g_sd_vpo_dev = (struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 1);
	g_decv_dev = (struct vdec_device *)dev_get_by_id(HLD_DEV_TYPE_DECV, 0);

	vdec_open(g_decv_dev);
	InitVPPara(&tVPInitInfo,tv_mode, scart_out, tv_ratio, display_mode);
	vpo_open(g_vpo_dev,&tVPInitInfo);
	InitVPPara_sd(&tVPInitInfo,tv_mode, scart_out, tv_ratio, display_mode);
	vpo_open(g_sd_vpo_dev,&tVPInitInfo);

	return RET_SUCCESS;
}

void vpo_dev_attach(void)
{
    struct VP_Feature_Config vp_config;
    struct Tve_Feature_Config tve_config;
    struct Tve_Feature_Config sd_tve_config;

    MEMSET ( ( void * ) &tve_config, 0, sizeof ( struct Tve_Feature_Config ) );
    MEMSET ( ( void * ) &sd_tve_config, 0, sizeof ( struct Tve_Feature_Config ) );
    MEMSET ( ( void * ) &vp_config, 0, sizeof ( struct VP_Feature_Config ) );

    vp_config.bAvoidMosaicByFreezScr = FALSE;    /* macro VDEC_AVOID_MOSAIC_BY_FREEZE_SCR */

    vp_config.bMHEG5Enable = FALSE;                  /* macro  _MHEG5_ENABLE_ */

    vp_config.bOsdMulitLayer = FALSE;                  /* macro OSD_MULTI_LAYER */
    vp_config.bOvershootSolution = FALSE;            /* macro VIDEO_OVERSHOOT_SOLUTION */
    vp_config.bP2NDisableMAF = TRUE;
    vp_config.bSupportExtraWin = FALSE;                /* macro VIDEO_SUPPORT_EXTRA_DVIEW_WINDOW */
    vp_config.bADPCMEnable = FALSE;                   /* macro VIDEO_ADPCM_ONOFF(VIDEO_ADPCM_ON:TRUE VIDEO_ADPCM_OFF:FALSE) */
    vp_config.pMPGetMemInfo = NULL;
    vp_config.pSrcAspRatioChange_CallBack = NULL;//api_Scart_Aspect_Switch;

    tve_config.config = YUV_SMPTE | TVE_TTX_BY_VBI | TVE_CC_BY_VBI;

    tve_config.config |= TVE_NEW_CONFIG_1;
    tve_config.tve_tbl_all = tve_table_total;
    m36g_vpo_attach ( &vp_config, &tve_config );


    vcap_attach_t vcap_param;
    vcap_param.fb_addr = __MM_VCAP_FB_ADDR;
    vcap_param.fb_size = __MM_VCAP_FB_SIZE;
    m36g_vcap_attach ( &vcap_param );

    sd_tve_config.config = YUV_SMPTE | TVE_TTX_BY_VBI | TVE_CC_BY_VBI;

    sd_tve_config.tve_adjust = g_sd_tve_adjust_table;
    sd_tve_config.tve_adjust_adv = tve_sd_adjust_table_adv;
    m36g_vpo_sd_attach ( &vp_config, &sd_tve_config );
}

void vdec_dev_attach(void)
{
    /* !!!!!Note !!!!!
            If you copy this code to other project, please check feature configuration firstly
         !!!!!Note !!!!!
    */
    struct vdec_config_par vdec_config_par;

    memset ( ( void * ) &vdec_config_par, 0, sizeof ( struct vdec_config_par ) );
    //vdec_config_par.mem_map.frm0_Y_size  = 0;
    vdec_config_par.mem_map.frm0_Y_size  = __MM_FB_LEN;
    vdec_config_par.mem_map.frm0_C_size = 0;
    vdec_config_par.mem_map.frm1_Y_size  = 0;
    vdec_config_par.mem_map.frm1_C_size = 0;
    vdec_config_par.mem_map.frm2_Y_size = 0;
    vdec_config_par.mem_map.frm2_C_size = 0;

    vdec_config_par.mem_map.frm0_Y_start_addr = __MM_FB_START_ADDR;
    vdec_config_par.mem_map.frm0_C_start_addr = 0;
    vdec_config_par.mem_map.frm1_Y_start_addr = 0;
    vdec_config_par.mem_map.frm1_C_start_addr = 0;
    vdec_config_par.mem_map.frm2_Y_start_addr = 0;
    vdec_config_par.mem_map.frm2_C_start_addr = 0;

    vdec_config_par.mem_map.dvw_frm_size = 0;
    vdec_config_par.mem_map.dvw_frm_start_addr = 0;

    vdec_config_par.mem_map.maf_size = __MM_MAF_LEN;
    vdec_config_par.mem_map.maf_start_addr = __MM_MAF_START_ADDR;

    vdec_config_par.mem_map.vbv_size = ((__MM_VBV_LEN-4)&0xFFFFFF00);
    vdec_config_par.mem_map.vbv_start_addr = ((__MM_VBV_START_ADDR&0xfffffff)|0x80000000);
    vdec_config_par.mem_map.vbv_end_addr = \
        ((vdec_config_par.mem_map.vbv_start_addr) +  vdec_config_par.mem_map.vbv_size - 1);

    vdec_config_par.user_data_parsing = TRUE; /* macro USER_DATA_PARSING */
    vdec_config_par.dtg_afd_parsing = 0;     //SUPPORT_AFD_SCALE
    vdec_config_par.drop_freerun_pic_before_firstpic_show = FALSE; /* macro VDEC27_DROP_FREERUN_BEFORE_FIRSTSHOW */
    vdec_config_par.reset_hw_directly_when_stop = TRUE;  /* macro VDEC27_STOP_REST_HW_DIRECTLY*/
    vdec_config_par.show_hd_service = FALSE;      /* macro SUPPORT_SHOW_HD_SERVICE */
    vdec_config_par.still_frm_in_cc = FALSE;          /* macro STILL_FRAME_IN_CC */
    vdec_config_par.not_show_mosaic = FALSE;      /* macro VDEC_AVOID_MOSAIC_BY_FREEZE_SCR */
    vdec_config_par.adpcm.adpcm_mode = FALSE;  /* macro VIDEO_ADPCM_ONOFF(VIDEO_ADPCM_ON:TRUE VIDEO_ADPCM_OFF:FALSE)*/
    vdec_config_par.adpcm.adpcm_ratio = 0;
    vdec_config_par.sml_frm.sml_frm_mode = FALSE;  /* macro VDEC27_SML_FRM_ONOFF(VDEC27_SML_FRM_OFF: FALSE   VDEC27_SML_FRM_ON: TRUE)*/
    vdec_config_par.return_multi_freebuf = TRUE;        /* macro VDEC27_SUPPORT_RETURN_MULTI_FREEBUF */
    vdec_config_par.sml_frm.sml_frm_size = 0;           /* macro VDEC27_SML_FRM_SIZE*/
    vdec_config_par.lm_shiftthreshold = 2;                   /* macro VDEC27_LM_SHIFTTHRESHOLD*/
    vdec_config_par.vp_init_phase = 0;                        /* macro DEFAULT_MP_FILTER_ENABLE*/
    vdec_config_par.preview_solution = VDEC27_PREVIEW_DE_SCALE; /* macro VDEC27_PREVIEW_SOLUTION(VDEC27_PREVIEW_VE_SCALE or VDEC27_PREVIEW_DE_SCALE)*/
    vdec_m36_attach ( &vdec_config_par );
}

void set_scart_gpio(void)
{
    if (sys_ic_get_chip_id() == ALI_S3503)
    {
        if (sys_ic_get_package_id() == 0x1)
        { // M3512
            HAL_GPIO_BIT_DIR_SET(37, 1);
            HAL_GPIO_BIT_SET(37, 0);
            HAL_GPIO_BIT_DIR_SET(38, 1);
            HAL_GPIO_BIT_SET(38, 0);
            HAL_GPIO_BIT_DIR_SET(39, 1);
            HAL_GPIO_BIT_SET(39, 0);

          // M3516
            HAL_GPIO_BIT_DIR_SET(33, 1);
            HAL_GPIO_BIT_SET(33, 0);
            HAL_GPIO_BIT_DIR_SET(34, 1);
            HAL_GPIO_BIT_SET(34, 0);
        }
        else if (sys_ic_get_package_id() == 0x4)
        { // M3515
            HAL_GPIO_BIT_DIR_SET(129, 1);
            HAL_GPIO_BIT_SET(129, 0);
            HAL_GPIO_BIT_DIR_SET(130, 1);
            HAL_GPIO_BIT_SET(130, 0);
            HAL_GPIO_BIT_DIR_SET(131, 1);
            HAL_GPIO_BIT_SET(131, 0);
        }
        else if (sys_ic_get_package_id() == 0x3)
        { // M3511
            HAL_GPIO_BIT_DIR_SET(18, 1);
            HAL_GPIO_BIT_SET(18, 0);
            HAL_GPIO_BIT_DIR_SET(88, 1);
            HAL_GPIO_BIT_SET(88, 0);
            HAL_GPIO_BIT_DIR_SET(89, 1);
            HAL_GPIO_BIT_SET(89, 0);
        }
    }
    else if (sys_ic_get_chip_id() == ALI_S3821)
    {
        if (sys_ic_get_package_id() == 0xf)
        { // M3822
            HAL_GPIO_BIT_DIR_SET(19, 1);
            HAL_GPIO_BIT_SET(19, 0);
            HAL_GPIO_BIT_DIR_SET(76, 1);
            HAL_GPIO_BIT_SET(76, 0);
        }
        else if (sys_ic_get_package_id() == 0x0)
        { // M3823
            HAL_GPIO_BIT_DIR_SET(60, 1);
            HAL_GPIO_BIT_SET(60, 0);
            HAL_GPIO_BIT_DIR_SET(19, 1);
            HAL_GPIO_BIT_SET(19, 0);
        }
        /*else if (sys_ic_get_package_id() == 0x1)
        { // M3821
            HAL_GPIO_BIT_DIR_SET(19, 1);
            HAL_GPIO_BIT_SET(19, 0);
            HAL_GPIO_BIT_DIR_SET(20, 1);
            HAL_GPIO_BIT_SET(20, 1);
        }*/
    }
}
INT32 check_videologo_playback_status(void)
{
	return videologo_playback_end;
}

void set_videologo_playback_status(INT32 playback_flag)
{
    videologo_playback_end = playback_flag;
}

static void monitor_logoplayback_task(void)
{
	struct VDec_StatusInfo cur_status;
    struct TRANS_VDEC_INFO vdec_info;

	do
    {
    	vdec_io_control(g_decv_dev, VDEC_IO_GET_STATUS, (UINT32)&cur_status);

        if(cur_status.uFirstPicShowed)
    	{
    		if(!cur_status.top_cnt)
    		{
    			if(cur_status.valid_size < 1024)
    			{
    				if(1 != flag_changed)
    				{
    					flag_changed = 1;
                        vdec_info.pic_width = cur_status.pic_width;
                        vdec_info.pic_height = cur_status.pic_height;
                        vdec_info.aspect_ratio = cur_status.aspect_ratio;
                        vdec_info.resv[0] = 1;
                        set_sysinfo_from_bl(TRANS_VDEC_TYPE, (UINT8 *)&vdec_info);
                        set_videologo_playback_status(1);
    				}
    			}
    		}
    	}
        osal_task_sleep(100);
	}while(1);
}

RET_CODE monitor_logoplayback_task_init(void)
{
	ID control_task_id = OSAL_INVALID_ID;
	OSAL_T_CTSK t_ctsk;

	t_ctsk.stksz = 0x4000+0x5000;//CONTROL_TASK_STACKSIZE+0x5000;
	t_ctsk.quantum = 10;//CONTROL_TASK_QUANTUM;
	t_ctsk.itskpri = OSAL_PRI_NORMAL;
	t_ctsk.name[0] = 'L';
	t_ctsk.name[1] = 'L';
	t_ctsk.name[2] = 'L';

	t_ctsk.task = (FP)monitor_logoplayback_task;

	control_task_id = osal_task_create(&t_ctsk);
	if(OSAL_INVALID_ID == control_task_id)
	{
		return RET_FAILURE;
	}
    else
    {
    	return RET_SUCCESS;
    }
}

RET_CODE bl_show_logo(UINT8 *buf, UINT32 len)
{
	RET_CODE ret_code = RET_FAILURE;
    UINT32 req_size;
	UINT32 got_size;
    INT32 repeat_time;
	INT32 left_size = len;
	char *temp_buf = buf;
	void *pwrite_buff = NULL;
	struct de2Hdmi_video_infor llvs;
    struct snd2Hdmi_audio_infor llas;
    UINT8 lastbuf[32] = {0};
    UINT8 tv_mode = 0;
	UINT8 scart_out = 0;
	UINT8 tv_ratio = 0;
    UINT8 display_mode = 0;
    INT32 ret = SUCCESS;
    UINT16	screen_width;
	UINT16	screen_height;
    
	if (buf == NULL)
	{
		FIXED_PRINTF("Logo buffer is null\n");
		return RET_FAILURE;
	}

    ret = bl_get_tv_set(&tv_mode,&scart_out, &tv_ratio, &display_mode);
    if(ret != SUCCESS)
    {
        //set default value
        tv_mode = TV_MODE_1080I_25;
        scart_out = SCART_YUV;
		//tv_ratio = TV_ASPECT_RATIO_169; // 16:9
		tv_ratio = TV_ASPECT_RATIO_AUTO; // aspect default set to auto
		display_mode = DISPLAY_MODE_PANSCAN;
    }
    
	llvs.tv_mode = tvmode_to_tvsys(tv_mode, scart_out);//10;
	llvs.afd_present = TRUE;
	llvs.scan_mode = logo_data_is_progressive(tv_mode);//FALSE;
	llvs.format = 4;
	llvs.output_aspect_ratio = tv_ratio;
	llvs.active_format_aspect_ratio = 8;

    bl_get_show_para(llvs.tv_mode, &screen_width, &screen_height);
	llvs.width = screen_width;
	llvs.height = screen_height;

	llvs.av_chg_ste = HDMI_CB_NOTHING;
	llas.av_chg_ste = HDMI_CB_NOTHING;

	set_scart_gpio();
	vpo_dev_attach();
	vdec_dev_attach();
	avInit(tv_mode, scart_out, tv_ratio, display_mode);
	avStart(llvs.tv_mode, llvs.scan_mode);

	/************config_de**************/
    if(sys_ic_get_chip_id()!=ALI_S3821)
    {
        VOU_CTRL = VOU_CTRL&(~(1<<2));  
        osal_delay(5);
        VOU_CFG_HDMI = VOU_CFG_HDMI|(1<<20);
        osal_delay(5);
        VOU_CFG_HDMI = VOU_CFG_HDMI |0x02;
        osal_delay(5);  
        VOU_CTRL = VOU_CTRL|(1<<2)|0x01;
    }
	/**************config_de*************/

	ret_code = vdec_start(g_decv_dev);
	if (ret_code != RET_SUCCESS)
	{
		FIXED_PRINTF("Start Vdec error\n");
		return ret_code;
	}

    repeat_time = 5;
    do
    {
        req_size = (left_size < VBV_REQ_SIZE)? left_size : VBV_REQ_SIZE;
        ret_code = vdec_vbv_request(g_decv_dev, req_size, &pwrite_buff, &got_size, NULL);
    	if (ret_code != RET_SUCCESS)
    	{
    		FIXED_PRINTF("Request VBV buffer error\n");
            repeat_time--;
    		continue;
    	}

    	osal_cache_flush(buf, got_size);
    	hld_dev_memcpy(pwrite_buff, buf, got_size);

	    buf += got_size;
	    left_size -= got_size;
        repeat_time = 5;

    	vdec_vbv_update(g_decv_dev, got_size);
    	//must delay for a  moment, otherwise will be crash
    	osal_task_sleep(10);
    }while ((left_size > 0) && (repeat_time > 0));

    //Send 32 bytes zero at the end
    memset(lastbuf, 0x0, 32);
    repeat_time = 5;
    do
	{
        ret_code = vdec_vbv_request(g_decv_dev, 32, &pwrite_buff, &got_size, NULL);
        repeat_time--;
        osal_task_sleep(10);
	}while ((RET_SUCCESS != ret_code) && (repeat_time > 0));
    hld_dev_memcpy(pwrite_buff, lastbuf, 32);
    vdec_vbv_update(g_decv_dev, 32);
    osal_task_sleep(10);

	hdmi_show_on_bootloader(&llvs, &llas);
	ret_code = monitor_logoplayback_task_init();

	return ret_code;
}

#endif

